import { GlobalContext } from '../app'
import { configs } from './configs'
import { globalStore } from './store'
import westore, { Store, StoreDataType } from './westore'

const defaultPageMembers = ['setData', 'data']

type ExcludePageKeys = 'name' | 'initData' | 'options' | 'setWechatContext' | 'update' | 'store'

export class PageBuilder {
  public static build<P extends Constructor<AppPage<any, any>>>(PageClass: P) {
    let page = new PageClass()
    const name = page.name
    let pageOptions: PageInitData<AppPage<any, any>['data']> = {
      data: {
        ...page.initData,
        // NOTE: 加入 globaStore 和 对应页面的 store 到 data 中
        ...globalStore.data,
        [name]: westore.getStoreData(name),
        assetsDir: configs.assetsDir,
        templateDatas: {
          assetsDir: configs.assetsDir
        }
      },

      onLoad(params: any) {
        page.options = params
        page.setWechatContext(this)
        page.onLoad(params)
      },

      onReady: page.onReady.bind(page),
      onShow: page.onShow.bind(page),
      onHide: page.onHide.bind(page),
      onUnload: page.onUnload.bind(page)
    }

    for (const key in page) {
      const k = key as Exclude<keyof typeof page, ExcludePageKeys>
      if (typeof (page as any)[k] === 'function' && !pageOptions[k]) {
        let shouldIgnore = false
        for (let name of defaultPageMembers) {
          if (key === name) {
            shouldIgnore = true
            break
          }
        }
        if (shouldIgnore) {
          continue
        }
        pageOptions[k] = ((page as any)[key] as Function).bind(page)
      }
    }
    console.log('pageOptions:', pageOptions)
    // NOTE: 由 westore 接管
    westore.create(name, pageOptions)
    // Page(pageOptions)
  }
}

type PageInstance = Page.PageInstance & { update: (data?: StoreDataType<any>) => void }
export abstract class AppPage<N extends keyof PageOptions, D> {
  public abstract name: N
  public abstract initData: Partial<D>
  public options!: PageOptions[N]
  public data: D & Pick<Store<N>['data'], N> = {} as D & Pick<Store<N>['data'], N> & typeof globalStore.data
  public store!: Store<N>
  private wechatContext!: PageInstance

  /** 生命周期函数--监听页面加载 */
  public abstract onLoad(options: this['options']): void

  /** 生命周期函数--监听页面渲染完成 */
  public onReady(): void { }

  /** 生命周期函数--监听页面显示 */
  public onShow(): void { }

  /** 生命周期函数--监听页面隐藏 */
  public onHide(): void { }

  /** 生命周期函数--监听页面卸载 */
  public onUnload(): void { }

  public setData(data: Partial<D>, callback?: () => void) {
    this.data = Object.assign(this.data, data)
    if (this.wechatContext.setData) {
      this.wechatContext.setData(data, callback)
    }
  }

  public setWechatContext(context: any) {
    this.wechatContext = context
    this.data = context.data
    this.store = context.store
  }

  protected getApp(): GlobalContext {
    return getApp() as any
  }
}
